package com.lightsh.utility;

import java.util.Collection;
import java.util.Iterator;
import java.util.Random;

import org.jbox2d.common.Vec2;

import android.graphics.Path;
import android.graphics.Rect;
import android.util.Log;

public class GeometryUtility {
	public static final float radianToAngle(float radian){
		return radian * Constants.RAD_TO_DEG;
	}
	public static final float angleToRadian(float angle){
		return angle * Constants.DEG_TO_RAD;
	}
	
	public static final boolean isEqual(float a, float b, float range){
		return Math.abs(a - b) < range;
	}
	
	public static final float getDistance(float x, float y, float x1, float y1){
		return (float) Math.sqrt(Math.pow(Math.abs(x - x1),2) + Math.pow(Math.abs(y - y1), 2));
	}
	
	public static final float getTargetRadian(float originX, float originY, float x, float y){
		float xDistance = x - originX;
		float yDistance = y - originY;
		double targetRadian = Math.atan(yDistance / xDistance);
		
		boolean isOnOriginRight = x - originX > 0;
		boolean isOnOriginBottom = y - originY > 0;
		
		// 需要根据原点与目标点的位置判断当前的弧度值
		if(targetRadian > 0){
			if(isOnOriginRight || isOnOriginBottom){
				// 右下角
			}else{
				// 左上角
				targetRadian += Math.PI;
			}
		}else if(targetRadian < 0){
			// 小于零
			if(isOnOriginRight || !isOnOriginBottom){
				// 右上角
				targetRadian = Math.PI * 2 + targetRadian;
			}else{
				// 左下角
				targetRadian = Math.PI + targetRadian;
			}
		}else{
			// 等于0
			if(isOnOriginRight){
				targetRadian = 0;
			}else{
				targetRadian = Math.PI;
			}
		}
		return (float) targetRadian;
	}
	public static final float getTargetAngle(float originX, float originY, float x, float y){
		return radianToAngle(getTargetRadian(originX, originY, x, y));
	}
	
	/**
	 * 根据给定的目标点与原点的距离值，计算出与参考点相同方向的目标点坐标
	 * @param originX
	 * @param originY
	 * @param referenceX
	 * @param referenceY
	 * @param targetDistance
	 * @return
	 */
	public static final Vec2 getScalePoint(float originX, float originY, float referenceX, float referenceY, float targetDistance){
		double distance = GeometryUtility.getDistance(originX, originY, referenceX, referenceY);
		float scale = (float) (targetDistance / distance);		
		float targetX = originX + scale * (referenceX - originX);
		float targetY = originY + scale * (referenceY - originY);
		return new Vec2(targetX, targetY);
	}
	
	/**
	 * 根据给定的目标点弧度和距离，计算出目标点坐标
	 * @param originX			原点x坐标
	 * @param originY			原点y坐标
	 * @param targetRadian		目标角度
	 * @param targetDistance	距离原点的距离
	 * @return					转换后的坐标
	 */
	public static final Vec2 getTargetRadianPoint(float originX, float originY, float targetRadian, float targetDistance){
		float targetX = (float) (Math.cos(targetRadian) * targetDistance);
		float targetY = (float) (Math.sin(targetRadian) * targetDistance);
		return new Vec2(originX + targetX, originY + targetY);
	}
	
	/**
	 * 判断圆形是否在目标范围内
	 * @param centerVec			圆形中心点,单位为缩放前
	 * @param radius			半径,单位为缩放前
	 * @param rect				目标矩形,单位为缩放后
	 * @param selfScale				缩放比例
	 * @return					如果在矩形范围内(有重叠)，返回true
	 */
	public static boolean isCircleInRect(Vec2 centerVec, float radius, Rect rect, float selfScale){
		final float realX = centerVec.x / selfScale;
		final float realY = centerVec.y / selfScale;
		
		final float realRadius = radius / selfScale;		
		final float maxWidth = rect.width() / 2 + realRadius;
		final float maxHeight = rect.height() / 2 + realRadius;
		
		return Math.abs(realX - (rect.left + rect.right) / 2) < maxWidth
			&& Math.abs(realY - (rect.top + rect.bottom) / 2) < maxHeight;
	}
	public static boolean isInRectCenter(Vec2 rectangleCenter, float halfWidth, float halfHeight, Rect rect, float selfScale){
		Vec2 vec2 = new Vec2(rectangleCenter.x - halfWidth, rectangleCenter.y - halfHeight);
		return isInRect(vec2, halfWidth * 2, halfHeight * 2, rect, selfScale);
	}
	public static boolean isInRect(Vec2 leftTopPoint, float width, float height, Rect rect, float selfScale){
		Vec2 vec2 = new Vec2(leftTopPoint.x / selfScale, leftTopPoint.y / selfScale);
		return isInRect(vec2, width / selfScale, height / selfScale, rect);
	}
	public static boolean isInRect(Vec2 leftTopPoint, float width, float height, Rect rect){
		return leftTopPoint.x < rect.right && leftTopPoint.x + width > rect.left
				&& leftTopPoint.y < rect.bottom && leftTopPoint.y + height > rect.top;
	}
	
	private static float getPolygonRadius(Vec2 centerPoint, Collection<Vec2> vertexs){
		float maxDis = 0;
		for(Vec2 vec : vertexs){
			maxDis = (float) Math.max(maxDis, Math.pow(vec.x, 2) + Math.pow(vec.y, 2));
		}
		maxDis = (float) Math.sqrt(maxDis);
		return maxDis;
	}
	public static boolean isPolygonInRect(Vec2 centerPoint, Collection<Vec2> vertexs, Rect rect, float selfScale){
		// 将里中心最远的点的距离作为半径判断是否需要绘制
		float maxDis = getPolygonRadius(centerPoint, vertexs);
		return GeometryUtility.isCircleInRect(centerPoint, maxDis, rect, selfScale);
	}
	
	/**
	 * 判断点是否在圆形内
	 * @param center			圆的中心点(注意: 如果圆自己本身进行了缩放，即有selfScale，这里的中心点应该是对缩放进行还原的值)
	 * @param radius			半径(注意: 需要与center参数相同的处理)
	 * @param worldScale		世界的缩放
	 * @param screenX			屏幕左上角x坐标
	 * @param screenY			屏幕左上角y坐标
	 * @param point				需要判断的point
	 * @return					指定点是否在圆内
	 */
	public static boolean isPointInCircle(Vec2 center, float radius, float worldScale, float screenX, float screenY, Vec2 point){
		if(worldScale == 1 && screenX == 0 && screenY == 0){
			return isPointInCircle(center, radius, point);
		}else{
			// 将目标图形的位置根据屏幕的位置和缩放进行转换，转换成相对于屏幕的位置
			Vec2 centerPosition = new Vec2(center.x - screenX, center.y - screenY).mulLocal(worldScale);
			float realRadius = radius * worldScale;
			return isPointInCircle(centerPosition, realRadius, point);
		}
	}
	private static boolean isPointInCircle(Vec2 center, float radius, Vec2 point){
		return Math.abs(point.x - center.x) <= radius && Math.abs(point.y - center.y) <= radius;
	}
	
	public static boolean isPointInRectangle(Vec2 rectangleCenter, float worldScale, float screenX, float screenY, float halfWidth, float halfHeight, Vec2 point){
		if(worldScale == 1 && screenX == 0 && screenY == 0){
			return isPointInRectangle(rectangleCenter, halfWidth, halfHeight, point);
		}else{
			Vec2 centerPosition = new Vec2(rectangleCenter.x - screenX, rectangleCenter.y - screenY).mulLocal(worldScale);
			float realHalfW = halfWidth * worldScale;
			float realHalfH = halfHeight * worldScale;
			return isPointInRectangle(centerPosition, realHalfW, realHalfH, point);
		}
	}
	private static boolean isPointInRectangle(Vec2 rectangleCenter, float halfWidth, float halfHeight, Vec2 point){
		return Math.abs(point.x - rectangleCenter.x) <= halfWidth && Math.abs(point.y - rectangleCenter.y) <= halfHeight;
	}
	
	public static boolean isPointInPolygon(Vec2 centerPoint, Collection<Vec2> vertexs, float worldScale, float screenX, float screenY, Vec2 point){
		Utility.fixme();
		float maxDis = getPolygonRadius(centerPoint, vertexs);
		// FIXME 这里的位置判断能否优化？
		return isPointInCircle(centerPoint, maxDis, worldScale, screenX, screenY, point);
	}
	private static boolean isPointInPolygon(Vec2 centerPoint, Collection<Vec2> vertexs, Vec2 point){
		float maxDis = getPolygonRadius(centerPoint, vertexs);
		// FIXME 这里的位置判断能否优化？
		return isPointInCircle(centerPoint, maxDis, point);
	}
	
	/**
	 * 根据多边形的状态，输出路径到path中
	 */
	public static void trackPolygonPath(Path mPath, Vec2 center, Collection<Vec2> polygonVertexs, float[] vertices, 
			float selfScale, float worldScale, float beginLeft, float beginTop){
		mPath.reset();
//		Log.e("position", vec2.x / scale + "," + vec2.y / scale);
//		Log.d("worldCenter", mBody.getWorldCenter().x / scale + "," + mBody.getWorldCenter().y/scale);
//		Log.w("localCenter", mBody.getLocalCenter().x / scale + "," + mBody.getLocalCenter().y/scale);
		int j = 0;
		boolean first = true;
		for(Vec2 point : polygonVertexs){
			vertices[j++] = point.x + center.x;
			vertices[j++] = point.y + center.y;
			if (first){
				first = false;
				mPath.moveTo((vertices[j - 2] / selfScale - beginLeft) * worldScale, (vertices[j - 1] / selfScale - beginTop) * worldScale);
			} else{
				mPath.lineTo((vertices[j - 2] / selfScale - beginLeft) * worldScale, (vertices[j - 1] / selfScale - beginTop) * worldScale);
			}
		}
		mPath.close();
	}
}
